package com.mycat.manager.content;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.google.gson.Gson;
import com.mycat.common.util.CommonUtil;

/**
 * AOP日志管理
 *
 * @author Roger
 */
@Aspect
@Component
public class AOPAdvice {

    private static final Logger logger = LoggerFactory.getLogger(AOPAdvice.class);

    /**
     * 配置切入点
     */
    @Pointcut("execution(public * com.mycat.manager.controller.help.*.*(..))")
    private void outputLogMethod1() {
    }

    /**
     * 配置切入点
     */
    @Pointcut("execution(public * com.mycat.manager.controller.auth.*.*(..))")
    private void test() {
    }

    /**
     * 在方法之前执行一段逻辑
     *
     * @param joinPoint 被拦截接口的入参
     */
    @Before("outputLogMethod1() || test()")
    public void beforeAdvice(JoinPoint joinPoint) {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        logger.info("请求地址 : " + request.getRequestURI().toString());
        logger.info("请求方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "()");

        Object[] params = joinPoint.getArgs();

        if (null != params) {
            // 输入参数
            StringBuffer inputParam = new StringBuffer();
            Gson gson = new Gson();
            for (int i = 0; i < params.length; i++) {
                Object param = params[i];
                if (null != param) {
                    if (!CommonUtil.isBaseType(param)) {
                        if (param instanceof HttpServletRequest) {
                            continue;
                        } else if (param instanceof HttpServletResponse) {
                            continue;
                        } else if (param instanceof Model) {
                            continue;
                        } else {
                            inputParam.append(String.format(" [%s]", i));
                            inputParam.append(String.format("[%s]", param.getClass().getName()));
                            if (i == params.length - 1) {
                                inputParam.append("-->").append(gson.toJson(param).toString()).append(" ");
                            } else {
                                inputParam.append("-->").append(gson.toJson(param).toString()).append(" , ");
                            }
                        }
                    } else {
                        inputParam.append(String.format("[%s]", i));
                        if (i == params.length - 1) {
                            inputParam.append("-->").append(param).append(" ");
                        } else {
                            inputParam.append("-->").append(param).append(" , ");
                        }
                    }
                } else {
                    logger.info("请求参数 : 无 .");
                }
            }
            logger.info("请求参数 : 【" + inputParam.toString() + "】");
        } else {
            logger.info("请求参数 : 无 .");
        }
    }

    /**
     * 在方法之后执行一段逻辑
     *
     * @param joinPoint 被拦截接口的入参
     */
    @After("outputLogMethod1()")
    public void afterAdvice(JoinPoint joinPoint) {
    }

    /**
     * 在请求前后执行一段逻辑
     *
     * @param pjp 被拦截接口的入参
     * @return
     * @throws Throwable
     */
    @Around("outputLogMethod1() || test()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        // 调用核心逻辑
        Object retVal = pjp.proceed();
        try {
            String str = "";
            if (CommonUtil.isNotEmpty(retVal)) {
                Gson gson = new Gson();
                str = gson.toJson(retVal);
                logger.info("响应数据  : " + str);
            } else {
                logger.info("返回类型是 Void");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retVal;
    }
}
